package com.zhou.org.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhou.org.common.RightKeyEnum;
import com.zhou.util.Assert;
import com.zhou.util.NumberUtil;
import com.zhou.org.common.EnumConstant;
import com.zhou.org.common.MenuCache;
import com.zhou.org.common.RightUtil;
import com.zhou.org.dao.Menu;
import com.zhou.org.dao.Right;
import com.zhou.framework.dto.TwoIntegerDto;
import com.zhou.org.dto.MenuDto;
import com.zhou.org.dto.MenuQueryDto;
import com.zhou.org.mapper.MenuMapper;
import com.zhou.org.model.MenuTree;
import com.zhou.org.service.MenuService;
import com.zhou.org.service.RightService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lang.zhou
 * @since 2022-08-23
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Autowired
    private RightService rightService;

    @Override
    public void saveMenu(Menu menu) {
        menu.setUpdateDt(new Date());
        int lastMenuId= menu.getLastMenuId();

        Assert.isTrue(lastMenuId== 0 || !Objects.equals(lastMenuId,menu.getId()),"保存的菜单数据错误！");
        if(NumberUtil.upper0(menu.getId())){
            List<MenuTree> list= getMenuTree();
            Map<Integer,Integer> lm = new HashMap<>(list.size()*3);
            this.readMenuLevel(list,1,lm);
            Integer lc = lm.get(menu.getId());
            Integer lp = lm.get(lastMenuId);
            if(lastMenuId == 0){
                lp = 0;
            }
            Assert.isTrue(lc != null && lp != null,"无法读取到菜单层级！");
            Assert.isTrue(lc - lp == 1,"保存菜单不能跨层级！");
        }
        if(NumberUtil.upper0(menu.getId())){
            updateById(menu);
        }else{
            save(menu);
        }
        MenuCache.reloadMenu();
    }
    private void readMenuLevel(List<MenuTree> list,int level,Map<Integer,Integer> lm){
        for (MenuTree menu2 : list) {
            lm.put(menu2.getId(),level);
            if(menu2.getChilds() != null){
                readMenuLevel(menu2.getChilds(),level + 1,lm);
            }
        }
    }

    @Override
    public void deleteMenu(Integer id) {
        removeById(id);
        rightService.deleteRight(RightKeyEnum.MENU,String.valueOf(id));
        MenuCache.reloadMenu();
    }

    @Override
    public void moveMenu(TwoIntegerDto dto) {
        Menu menu = getById(dto.getId1());
        Assert.notNull(menu,"菜单不存在");
        if(NumberUtil.upper0(dto.getId2())){
            Menu parent = getById(dto.getId2());
            Assert.notNull(parent,"目标菜单不存在");
        }
        menu.setLastMenuId(dto.getId2());
        saveMenu(menu);
    }

    @Override
    public List<MenuDto> getPageList(MenuQueryDto dto) {
        return baseMapper.getPageList(dto);
    }

    @Override
    public List<Menu> getTopMenu() {
        QueryWrapper<Menu> query = new QueryWrapper<>();
        query.eq("last_menu_id",0);
        return list(query);
    }

    @Override
    public List<MenuTree> getMenuTree() {
        return baseMapper.getMenuTree(0);
    }

    @Override
    public List<MenuTree> getRightMenuTree(int orgId) {
        List<MenuTree> menus = baseMapper.getMenuTree(0);
        List<Right> rights = RightUtil.getRight(RightKeyEnum.MENU,"YES",orgId);
        List<Integer> idList = new ArrayList<>(rights.size()/2);
        for(Right right : rights){
            if (right.getReject() == 0){
                idList.add(NumberUtil.safeToInteger(right.getObjectKey(),0));
            }

        }
        removeMenu(menus,idList);
        return menus;
    }

    @Override
    public int getChildMenuCnt(Integer id) {
        QueryWrapper<Menu> query = new QueryWrapper<>();
        query.eq("last_menu_id",id);
        return baseMapper.selectCount(query);
    }

    private void removeMenu(List<MenuTree> menus,List<Integer> idList){
        Iterator<MenuTree> iterator = menus.iterator();
        while (iterator.hasNext()){
            MenuTree menu2 = iterator.next();
            if(!idList.contains(menu2.getId())){
                iterator.remove();
            }else{
                if(menu2.getChilds().size() > 0){
                    removeMenu(menu2.getChilds(),idList);
                }
            }
        }
    }

    @Override
    public List<Menu> listAll() {
        QueryWrapper<Menu> query = new QueryWrapper<>();
        query.orderByAsc("last_menu_id");
        query.orderByAsc("sort");
        return list(query);
    }

}
